package demo6;

import java.util.Stack;

public class InfixEvaluator {

    public static double evaluateInfix(String expression) throws ArithmeticException {
        Stack<Double> operandStack = new Stack<>();
        Stack<Character> operatorStack = new Stack<>();

        char[] tokens = expression.toCharArray();

        for (int i = 0; i < tokens.length; i++) {
            char token = tokens[i];

            // 跳过空格
            if (token == ' ') continue;

            // 如果是数字或小数点，读取完整数字
            if (Character.isDigit(token) || token == '.') {
                StringBuilder sb = new StringBuilder();
                while (i < tokens.length && (Character.isDigit(tokens[i]) || tokens[i] == '.')) {
                    sb.append(tokens[i]);
                    i++;
                }
                i--; // 回退一位
                operandStack.push(Double.parseDouble(sb.toString()));
            }
            // 如果是左括号，压入栈
            else if (token == '(') {
                operatorStack.push(token);
            }
            // 如果是右括号，依次计算直到遇到左括号
            else if (token == ')') {
                while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
                    processStacks(operandStack, operatorStack);
                }
                operatorStack.pop(); // 弹出左括号
            }
            // 如果是操作符
            else if (isOperator(token)) {
                while (!operatorStack.isEmpty() && precedence(operatorStack.peek()) >= precedence(token)) {
                    processStacks(operandStack, operatorStack);
                }
                operatorStack.push(token);
            }
        }

        // 处理剩余的操作符
        while (!operatorStack.isEmpty()) {
            processStacks(operandStack, operatorStack);
        }

        return operandStack.pop();
    }

    private static void processStacks(Stack<Double> operandStack, Stack<Character> operatorStack) throws ArithmeticException {
        double val2 = operandStack.pop();
        double val1 = operandStack.pop();
        char op = operatorStack.pop();

        switch (op) {
            case '+':
                operandStack.push(val1 + val2);
                break;
            case '-':
                operandStack.push(val1 - val2);
                break;
            case '*':
                operandStack.push(val1 * val2);
                break;
            case '/':
                if (val2 == 0) {
                    throw new ArithmeticException("除数不能为零");
                }
                operandStack.push(val1 / val2);
                break;
            case '%':
                operandStack.push(mod(val1, val2));
                break;
        }
    }

    private static double mod(double val1, double val2) {
        if (val2 == 0) {
            throw new ArithmeticException("除数不能为零");
        }
        return val1 - val2 * Math.floor(val1 / val2);
    }

    private static int precedence(char op) {
        if (op == '(') return 0; // '(' 优先级最低
        if (op == '+' || op == '-') return 1;
        if (op == '*' || op == '/' || op == '%') return 2;
        return -1;
    }

    private static boolean isOperator(char op) {
        return op == '+' || op == '-' || op == '*' || op == '/' || op == '%';
    }
}